<?php
namespace app\service;

/**
 * 设备指令下发服务
 */
class DeviceCommandService
{
    /**
     * 设备下发接口请求结构
     * 
     * @param array $requestData 请求数据
     * @return array 标准化的请求结构
     */
    public static function buildCommandRequest(array $requestData): array
    {
        return [
            // 必填字段
            'target' => [
                'type' => $requestData['target']['type'] ?? 'single', // single/batch/group
                'devices' => $requestData['target']['devices'] ?? [], // 设备标识列表
            ],
            'commands' => $requestData['commands'] ?? [], // 指令列表
            
            // 可选字段
            'options' => [
                'priority' => $requestData['options']['priority'] ?? 'normal', // high/normal/low
                'timeout' => $requestData['options']['timeout'] ?? 30, // 超时时间(秒)
                'retry_count' => $requestData['options']['retry_count'] ?? 3, // 重试次数
                'async' => $requestData['options']['async'] ?? true, // 是否异步执行
            ],
            
            // 元数据
            'metadata' => [
                'request_id' => $requestData['metadata']['request_id'] ?? uniqid('cmd_'), // 请求ID
                'source_system' => $requestData['metadata']['source_system'] ?? '', // 来源系统
                'operator' => $requestData['metadata']['operator'] ?? '', // 操作员
                'description' => $requestData['metadata']['description'] ?? '', // 操作描述
                'timestamp' => time(),
            ]
        ];
    }
    
    /**
     * 验证请求数据
     * 
     * @param array $requestData 请求数据
     * @return array [bool $isValid, string $errorMessage]
     */
    public static function validateRequest(array $requestData): array
    {
        // 验证必填字段
        if (empty($requestData['target']['devices'])) {
            return [false, '目标设备列表不能为空'];
        }
        
        if (empty($requestData['commands'])) {
            return [false, '指令列表不能为空'];
        }
        
        // 验证设备标识格式
        foreach ($requestData['target']['devices'] as $device) {
            if (!self::isValidDeviceIdentifier($device)) {
                return [false, "无效的设备标识: {$device}"];
            }
        }
        
        // 验证指令格式
        foreach ($requestData['commands'] as $command) {
            if (empty($command['cmd_name'])) {
                return [false, '指令名称不能为空'];
            }
        }
        
        return [true, ''];
    }
    
    /**
     * 验证设备标识是否有效
     * 
     * @param string $deviceId 设备标识
     * @return bool
     */
    private static function isValidDeviceIdentifier(string $deviceId): bool
    {
        // 可以是IMEI、MAC地址或设备序列号
        // IMEI: 15位数字
        if (preg_match('/^\d{15}$/', $deviceId)) {
            return true;
        }
        
        // MAC地址: XX:XX:XX:XX:XX:XX 或 XXXXXXXXXXXX
        if (preg_match('/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/', $deviceId) ||
            preg_match('/^[0-9A-Fa-f]{12}$/', $deviceId)) {
            return true;
        }
        
        // 设备序列号: 字母数字组合，6-20位
        if (preg_match('/^[A-Za-z0-9]{6,20}$/', $deviceId)) {
            return true;
        }
        
        return false;
    }
}

/**
 * 改进的IoT指令构建器
 */
class IoTCommandBuilder
{
    /**
     * 构建指令数组
     *
     * @param array $commands 指令列表
     * @return array
     */
    public static function buildCommands(array $commands): array
    {
        return [
            'cmds' => $commands
        ];
    }

    /**
     * 重启指令
     *
     * @param int $delay 延迟时间(秒)，默认立即执行
     * @return array
     */
    public static function reboot(int $delay = 0): array
    {
        $command = ['cmd_name' => 'reboot'];
        if ($delay > 0) {
            $command['cmd_params'] = ['delay' => $delay];
        }
        return $command;
    }

    /**
     * 关机指令
     *
     * @param int $delay 延迟时间(秒)
     * @return array
     */
    public static function powerOff(int $delay = 0): array
    {
        $command = ['cmd_name' => 'power_off'];
        if ($delay > 0) {
            $command['cmd_params'] = ['delay' => $delay];
        }
        return $command;
    }

    /**
     * 恢复出厂设置指令
     *
     * @param bool $keepNetworkConfig 是否保留网络配置
     * @return array
     */
    public static function recovery(bool $keepNetworkConfig = false): array
    {
        return [
            'cmd_name' => 'recovery',
            'cmd_params' => [
                'keep_network_config' => $keepNetworkConfig ? 1 : 0
            ]
        ];
    }

    /**
     * 修改热点信息指令
     *
     * @param array $params 热点参数
     * @return array
     */
    public static function hotspotModify(array $params): array
    {
        // 验证必要参数
        $validParams = [];
        
        // 热点名称
        if (isset($params['hotspot_name'])) {
            $validParams['hotspot_name'] = $params['hotspot_name'];
        }
        
        // 热点密码
        if (isset($params['hotspot_password'])) {
            if (strlen($params['hotspot_password']) < 8) {
                throw new \InvalidArgumentException('热点密码长度不能少于8位');
            }
            $validParams['hotspot_password'] = $params['hotspot_password'];
        }
        
        // 最大连接数
        if (isset($params['hotspot_connected_num_max'])) {
            $validParams['hotspot_connected_num_max'] = max(1, min(32, $params['hotspot_connected_num_max']));
        }
        
        // 是否隐藏
        if (isset($params['hotspot_whether_hide'])) {
            $validParams['hotspot_whether_hide'] = $params['hotspot_whether_hide'] ? 1 : 0;
        }
        
        // 频段设置
        if (isset($params['hotspot_band'])) {
            $validParams['hotspot_band'] = in_array($params['hotspot_band'], [0, 1]) ? $params['hotspot_band'] : 0;
        }
        
        return [
            'cmd_name' => 'hotspot_modify',
            'cmd_params' => $validParams
        ];
    }

    /**
     * 网络限速指令
     *
     * @param string $type 类型: download/upload/all
     * @param string $unit 单位: B/KB/MB/GB
     * @param float $value 数值
     * @return array
     */
    public static function networkSpeedLimit(string $type, string $unit, float $value): array
    {
        // 验证参数
        if (!in_array($type, ['download', 'upload', 'all'])) {
            throw new \InvalidArgumentException('限速类型必须是: download/upload/all');
        }
        
        if (!in_array($unit, ['B', 'KB', 'MB', 'GB'])) {
            throw new \InvalidArgumentException('单位必须是: B/KB/MB/GB');
        }
        
        if ($value <= 0) {
            throw new \InvalidArgumentException('限速值必须大于0');
        }
        
        return [
            'cmd_name' => 'network_speed_limit',
            'cmd_params' => [
                'type' => $type,
                'unit' => $unit,
                'value' => $value
            ]
        ];
    }

    /**
     * 切换SIM卡指令
     *
     * @param int $simId SIM卡ID: 0-卡槽1外置卡, 1-卡槽1内置卡, 2-卡槽2
     * @return array
     */
    public static function simSwitch(int $simId): array
    {
        if (!in_array($simId, [0, 1, 2])) {
            throw new \InvalidArgumentException('SIM卡ID必须是: 0/1/2');
        }
        
        return [
            'cmd_name' => 'sim_switch',
            'cmd_params' => [
                'sim_id' => $simId
            ]
        ];
    }

    /**
     * 立即上报指令
     *
     * @param array $reportTypes 上报类型: ['device_info', 'sim_info', 'system_info', 'network_info', 'hotspot_info']
     * @return array
     */
    public static function uploadNow(array $reportTypes = []): array
    {
        $command = ['cmd_name' => 'upload_now'];
        
        if (!empty($reportTypes)) {
            $validTypes = ['device_info', 'sim_info', 'system_info', 'network_info', 'hotspot_info'];
            $filteredTypes = array_intersect($reportTypes, $validTypes);
            
            if (!empty($filteredTypes)) {
                $command['cmd_params'] = ['report_types' => $filteredTypes];
            }
        }
        
        return $command;
    }
}
